/**
 *
 */
package com.naiterui.ehp.bs.doctor.service.impl;

import com.google.common.collect.Lists;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.domain.City;
import com.naiterui.ehp.bp.domain.Hospital;
import com.naiterui.ehp.bs.doctor.dao.ICityDao;
import com.naiterui.ehp.bs.doctor.dao.IHospitalDao;
import com.naiterui.ehp.bs.doctor.repository.ICityRepository;
import com.naiterui.ehp.bs.doctor.service.IHospitalService;
import com.naiterui.ehp.bs.doctor.utils.PropertyValueConstants;
import com.naiterui.ehp.bs.doctor.vo.HospitalVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AdHospitalServiceImpl implements IHospitalService {

    @Autowired
    private IHospitalDao hospitalDao;
    @Autowired
    private ICityDao cityDao;

    @Autowired
    private ICityRepository cityRepository;

    @Override
    public List<HospitalVO> getHopitalList(Integer cityId, String name, Integer max) {
        List<Hospital> hospitalList = hospitalDao.getHospitalListByCity(cityId, name, max);

        // 查询市级城市ID下属各区的医院
        if (StringUtils.isEmpty(name)) {
            City city = cityDao.get(cityId);
            if (city != null && city.getType().equals(PropertyValueConstants.AREA_TYPE_CITY)) {
                List<City> cityList = cityDao.getCityByPid(cityId);

                List<Hospital> hopsitals = getHopitalsByCitys(cityList, max);
                if (hopsitals.size() > 0) {
                    hospitalList.addAll(hopsitals);
                }
            }
        }

        Map<Integer, List<Hospital>> levelMap = handleHospitalLevel(hospitalList);
        List<Hospital> resultlist = handleHospitalName(levelMap);

        List<HospitalVO> voList = new ArrayList<>();
        for (Hospital hpt : resultlist) {
            HospitalVO vo = new HospitalVO();
            BeanUtils.copyProperties(hpt, vo);
            voList.add(vo);
        }
        return voList;

    }

    private Map<Integer, List<Hospital>> handleHospitalLevel(List<Hospital> hospitalList) {
        Map<Integer, List<Hospital>> levelMap = new HashMap<>();

        for (Hospital hospital : hospitalList) {
            switch (hospital.getLevelType()) {// 判断医院的等级
                case PropertyValueConstants.HOSPITAL_LEVEL_THREE_TOP:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_TOP) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_THREE_TOP, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_TOP).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_A:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_A) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_A, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_A).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_B:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_B) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_B, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_B).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_C:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_C) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_C, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_THREE_GRADE_C).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_A:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_A) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_A, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_A).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_B:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_B) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_B, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_B).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_C:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_C) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_C, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_TWO_GRADE_C).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_A:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_A) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_A, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_A).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_B:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_B) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_B, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_B).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_C:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_C) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_C, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_ONE_GRADE_C).add(hospital);
                    }
                    break;
                case PropertyValueConstants.HOSPITAL_LEVEL_GRADE_DEFALT:
                    if (levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_GRADE_DEFALT) == null) {
                        List<Hospital> hlist = new ArrayList<>();
                        hlist.add(hospital);
                        levelMap.put(PropertyValueConstants.HOSPITAL_LEVEL_GRADE_DEFALT, hlist);
                    } else {
                        levelMap.get(PropertyValueConstants.HOSPITAL_LEVEL_GRADE_DEFALT).add(hospital);
                    }
                    break;
                default:
                    break;
            }
        }
        return levelMap;
    }

    private List<Hospital> handleHospitalName(Map<Integer, List<Hospital>> levelMap) {
        List<Hospital> resultlist = new ArrayList<>();
        int[] hoslevelsequeces = PropertyValueConstants.HOSPITAL_LEVEL_SEQUENCES;
        for (int hoslevelsequece : hoslevelsequeces) {
            List<Hospital> hlist = levelMap.get(hoslevelsequece);
            Map<String, Hospital> map = new HashMap<>();
            if (hlist != null && hlist.size() > 0) {
                for (Hospital hospital2 : hlist) {
                    map.put(hospital2.getName(), hospital2);
                }
                /*
                 * 按照医院名称首字母排序
                 */
                Comparator comparator = Collator.getInstance(Locale.CHINA);
                String[] hosNameArray = map.keySet().toArray(new String[map.keySet().size()]);
                Arrays.sort(hosNameArray, comparator);
                for (String aHosNameArray : hosNameArray) {
                    resultlist.add(map.get(aHosNameArray));
                }
            }

        }
        return resultlist;

    }

    /**
     * 根据城市列表获取医院 HospitalServiceImpl.getHopitalsByCitys()
     * @Author guoyongxiang
     * @Date 2015年12月2日
     * @since 1.5.0
     * @param cityList
     * @return
     */
    private List<Hospital> getHopitalsByCitys(List<City> cityList, Integer max) {
        List<Integer> cityIds = new ArrayList<>();
        if (cityList != null && cityList.size() > 0) {
            for (City city : cityList) {
                cityIds.add(city.getId());
            }
        }
        List<Hospital> hopsitals = new ArrayList<>();
        if (cityIds.size() > 0) {
            if (null != max) {
                hopsitals = hospitalDao.getHospitalListByCitysLimit(cityIds, max);
            } else {
                hopsitals = hospitalDao.getHospitalListByCitys(cityIds);
            }
        }
        return hopsitals;
    }

    /**
     * 根据医院id查询医院信息
     * HospitalServiceImpl.getHospitalVo()
     * <p>@Param : </p>
     * <p>@Author : linhf</p>
     * <p>@Date : 2016年5月3日 下午5:53:58</p>
     * @return :
     */
    @Override
    public HospitalVO getHospitalById(Integer hospitalId) {
        Hospital hospital = hospitalDao.getHospitalById(hospitalId);
        HospitalVO vo = new HospitalVO();
        if (hospital != null) {
            vo.setId(hospital.getId());// 医院id
            vo.setName(hospital.getName());// 医生名称
            vo.setCityId(hospital.getCityId());// 医院所在城市id
        }
        return vo;
    }

    /**
     * 获取城市的医院，规则如下：
     * <pre>
     *     1. 优先显示该城市下的包含该关键字医院
     *     2. 其他非本城市的包含该关键字的医院，abc排序
     * </pre>
     * @return
     */
    @Override
    public List<HospitalVO> getHospitalByCity(String cityName, String key){
        List<HospitalVO> resultList = Lists.newArrayList();
        List<HospitalVO> hopitalList = getHopitalList(null, key, null);
        City city = cityRepository.findFirstByNameIsStartingWithAndTypeNotOrderByType(cityName, City.TYPE_PRO);

        //该城市下的医院列表
        if(city != null) {
            //该城市的直属区县
            List<City> cityList = cityRepository.findByAvailableAndParentIdOrderByIdAsc(CommonConstant.AVAILABLE_VALID, city.getId());
            List<Integer> cityIds = cityList.stream().map(s -> s.getId()).collect(Collectors.toList());
            cityIds.add(city.getId());

            resultList.addAll(hopitalList.stream().filter(s -> cityIds.contains(s.getCityId())).collect(Collectors.toList()));
            //其他城市的医院列表
            resultList.addAll(hopitalList.stream().filter(s -> !cityIds.contains(s.getCityId())).collect(Collectors.toList()));
        } else {
            resultList = hopitalList;
        }

        return resultList;
    }
}
